﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using System.IO;
namespace TinySkill
{

    public class SkillEditorWindow : EditorWindow
    {
        static SkillEditorWindow Instance;

        public delegate void DelegateOnActionChange();
        public static DelegateOnActionChange onActionChange;

        //分隔窗口
        Vector2 pos1;
        Vector2 pos2;
        Vector2 pos3;
        float splitterWidth1 = 200;
        float splitterWidth2 = 200;
        Rect splitterRect1;
        Rect splitterRect2;
        Vector2 dragStartPos;
        bool draggingLeft;
        bool draggingRight;
        float splitterWidth = 5;

        [MenuItem("技能编辑器/保存 %z")]
        static void Save()
        {
            SkillEditorEngine.Save();
        }
        [MenuItem("技能编辑器/刷新所有技能")]
        static void Refresh()
        {
            Data.LoadSkill();
            Refresh(true);
        }

        public static void Refresh(bool allDelete)
        {
            if (EditorSceneManager.GetActiveScene().name == "SkillEditor")
            {
                GameObject skillRoot = GameObject.Find("root");
                if (skillRoot != null && allDelete)
                    GameObject.DestroyImmediate(skillRoot);

                if (skillRoot == null)
                    skillRoot = new GameObject("root");

                List<config_skill> skills = new List<config_skill>();
                skills.AddRange(Data.Skill.Values);
                skills.Sort((a, b) => { return a.id < b.id ? -1 : 1; });

                bool dirty = allDelete;

                foreach (var s in skills)
                {
                    string obj_name = s.id.ToString() + ":" + s.name;
                    if (skillRoot.transform.Find(obj_name) == null)
                    {
                        GameObject skill = new GameObject(obj_name);
                        skill.transform.parent = skillRoot.transform;
                        skill.AddComponent<SkillObject>().id = s.id;
                        dirty = true;
                    }

                }
                if (dirty)
                {
                    MarkSceneDirty();
                }
            }

        }


#if DRAW_SKILL_LIST
    public List<config_skill> skills = new List<config_skill>();
    int selected_skill_index;
    GUIStyle styleSelectedSkill;

    config_skill selected_skill
    {
        get
        {
            if (selected_skill_index >= 0 && selected_skill_index < skills.Count)
                return skills[selected_skill_index];

            return null;
        }
    }


#else
        protected GameObject go;
        SkillObject myTarget
        {
            get
            {
                if (go != null)
                    return go.GetComponent<SkillObject>();
                return null;
            }
        }
        //public config_skill skill;
        //public config_skill_frame current_skill_frame;
        //int select_frame_index;
        // Has a GameObject been selection?

#endif

        config_skill _skill
        {
            get
            {
                if (myTarget != null)
                    return myTarget.skill;
                return null;
            }
        }

        int selected_frame_index
        {
            get { return myTarget.selected_frame_index; }
            set
            {
                if (myTarget.skill == null)
                    return;
                value = Mathf.Clamp(value, 0, myTarget.skill.frames.Length - 1);

                int last_select_frame = myTarget.selected_frame_index;
                myTarget.selected_frame_index = value;
                if (last_select_frame != value && onActionChange != null)
                {
                    onActionChange();
                }
            }
        }

        public config_skill_frame selected_frame
        {
            get
            {
                return myTarget.selected_frame;
            }
        }

        int selected_start_frame_index;
        int selected_end_frame_index;


        enum EditMode
        {
            None,
            Move,
            SelectFrame
        }
        EditMode _mode;
        Vector3 _lastMouseLocation;

        static config_skill_frame temp_frame;


        //Editor cacheEditor;
        //CustomTypeDrawer od = null;

        //static object last_selected_property
        //{
        //    get
        //    {
        //        return Instance.myTarget.last_selected_property;
        //    }
        //    set
        //    {
        //        if (Instance!=null && Instance.myTarget!=null)
        //            Instance.myTarget.last_selected_property = value;
        //    }
        //}

        void OnSelectProperty(object v)
        {
            if (Instance != null && Instance.myTarget != null)
                Instance.myTarget.last_selected_property = v;
        }

        void Awake()
        {
            Refresh(false);
            OnSelectionChange();
            //CustomPropertyDrawer.onSelectProperty = OnSelectProperty;
        }
        protected void OnEnable()
        {
            //SceneView.onSceneGUIDelegate += SceneGUI;
            CustomPropertyDrawer.onSelectProperty = OnSelectProperty;
            Instance = this;
            //Debug.Log("OnEnable");
            EditorApplication.playmodeStateChanged += OnPlayModeChanged;
            if (Data.Skill == null)
            {
                //Debug.Log("Reload");
                Data.LoadSkill();
            }

        }

        protected void OnDisable()
        {
            //SceneView.onSceneGUIDelegate -= SceneGUI;

            CustomPropertyDrawer.onSelectProperty = null;
            Instance = null;
            //Debug.Log("OnDisable");
            EditorApplication.playmodeStateChanged -= OnPlayModeChanged;

            //Debug.Log(Application.isPlaying);
            //播放状态下不自动保存数据
            if (EditorSceneManager.GetActiveScene().isDirty)
                EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
        }
        void OnDestroy()
        {
            SkillEditorEngine.Save();
            CustomPropertyDrawer.onSelectProperty = null;
        }


        void OnPlayModeChanged()
        {
            //Debug.LogFormat("playmode isPlaying {0}  isPaused {1}", EditorApplication.isPlaying, EditorApplication.isPaused);
            //脱离播放状态
            if (!(EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isPaused))
            {


                if (_isDirty)
                {
                    SkillEditorEngine.Save();
                    _isDirty = false;
                }
            }

            if (go != Selection.activeGameObject)
                OnSelectionChange();

        }

        //void SceneGUI(SceneView sceneView)
        //{
        //    if (Event.current.type == EventType.MouseDown
        //        && Event.current.button == 0)
        //    {
        //        RaycastHit hit;
        //        Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
        //        UnityEngine.Debug.DrawRay(ray.origin, ray.direction, Color.blue, 10);
        //        if (Physics.Raycast(ray, out hit))
        //        {
        //            UnityEngine.Debug.Log(hit.collider.gameObject);
        //        }

        //        UnityEngine.Debug.Log("Left-Mouse Down");
        //    }  
        //}


#if !DRAW_SKILL_LIST
        public void OnSelectionChange()
        {
            if (go != Selection.activeGameObject)
            {
                //Debug.Log("OnSelectionChange");
                go = Selection.activeGameObject;
                if (go != null && go.GetComponent<SkillObject>() != null)
                {
                    //使用当前类初始化
                    //myTarget = go.GetComponent<SkillObject>();
                    //od = null;
                    //selected_frame_index = 0;
                    //SceneView.RepaintAll();
                    //SkillEditorEngine engine = GameObject.Find("Engine").GetComponent<SkillEditorEngine>();
                    //engine.test_skill_id = myTarget.id;

                }

                Repaint();
            }
        }
#endif

        [MenuItem("Window/SkillEditor")]

        public static void ShowWindow()
        {
            EditorWindow.GetWindow(typeof(SkillEditorWindow));
        }


        void OnGUI()
        {
            if (go == null)
            {
                EditorGUILayout.HelpBox("请先选择技能", MessageType.Info);
                return;
            }

            if (_skill == null)
            {
                EditorGUILayout.HelpBox("无效的技能ID", MessageType.Info);
                return;
            }


            GUILayout.BeginHorizontal();


#if DRAW_SKILL_LIST
        // Left view
        pos1 = GUILayout.BeginScrollView(pos1, true, true,
            GUILayout.Width(splitterWidth1), GUILayout.MinWidth(splitterWidth1), GUILayout.MaxWidth(splitterWidth1));

        DrawSkills();

        GUILayout.EndScrollView();

        // Splitter
        GUILayout.Box("",
            GUILayout.Width(splitterWidth),
            GUILayout.MaxWidth(splitterWidth),
            GUILayout.MinWidth(splitterWidth),
            GUILayout.ExpandHeight(true));
        splitterRect1 = GUILayoutUtility.GetLastRect();

#endif


            DrawFrames();

            GUILayout.EndHorizontal();

            // Splitter events
            if (Event.current != null)
            {
                switch (Event.current.rawType)
                {
                    case EventType.MouseDown:
                        if (splitterRect1.Contains(Event.current.mousePosition))
                        {
                            //Debug.Log("Start dragging");
                            draggingLeft = true;
                        }
                        else if (splitterRect2.Contains(Event.current.mousePosition))
                        {
                            draggingRight = true;
                        }
                        if (Event.current.button == 0)
                            OnLeftMouseDown();
                        break;
                    case EventType.MouseDrag:
                        if (draggingLeft)
                        {
                            splitterWidth1 += Event.current.delta.x;
                            Repaint();
                        }
                        else if (draggingRight)
                        {
                            splitterWidth2 -= Event.current.delta.x;
                            Repaint();
                        }
                        if (Event.current.button == 0)
                            OnLeftMouseMove();

                        break;
                    case EventType.MouseMove:

                        break;
                    case EventType.MouseUp:
                        if (draggingLeft)
                        {
                            draggingLeft = false;
                        }
                        else if (draggingRight)
                        {
                            draggingRight = false;
                        }
                        if (Event.current.button == 0)
                            OnLeftMouseUp();
                        break;
                }

                if (Event.current.type == EventType.ContextClick)
                {

                    var contextRect = new Rect(title_width, time_scale_height, Screen.width, Screen.height);

                    if (contextRect.Contains(Event.current.mousePosition))
                    {
                        var menu = new GenericMenu();

                        menu.AddItem(new GUIContent("添加"), false, OnPopupMenuAdd);
                        menu.AddItem(new GUIContent("复制"), false, OnPopupMenuDup);
                        menu.AddItem(new GUIContent("删除"), false, OnPopupMenuDel);
                        menu.AddItem(new GUIContent("拷贝"), false, OnPopupMenuCopy);
                        menu.AddItem(new GUIContent("粘贴"), false, OnPopupMenuPrase);


                        menu.ShowAsContext();
                    }


                    Event.current.Use();
                }
            }
        }


        public static T GetCustomAttribute<T>(FieldInfo fi) where T : class
        {
            object[] atts = fi.GetCustomAttributes(typeof(T), false);
            if (atts != null && atts.Length > 0)
                return (T)atts[0];
            return null;
        }

        static bool _isDirty = false;
        public static void MarkSceneDirty()
        {
            if (!EditorApplication.isPlaying)
            {
                EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
            }
            else
            {
                _isDirty = true;
            }

        }

        void OnActionChange(object item)
        {
            selected_frame.action = (SkillFrameAction)System.Enum.Parse(typeof(SkillFrameAction), (string)item);
            selected_frame_index = selected_frame_index;
            if (selected_frame != null && config_skill_frame.action_types.ContainsKey(selected_frame.action))
            {
                System.Type actionType = config_skill_frame.action_types[selected_frame.action];
                System.Type dataType = selected_frame.data != null ? selected_frame.data.GetType() : null;
                if (actionType != dataType)
                {
                    selected_frame.data = config_skill_frame.Create(selected_frame.action);

                    MarkSceneDirty();
                }
            }

            Repaint();

            if (onActionChange != null)
                onActionChange();
        }

#if DRAW_SKILL_LIST
    Rect GetSelectedSkilRect()
    {
        Rect rectSelectSkill = new Rect(0, selected_skill_index * 30, splitterWidth1, 30);
        return rectSelectSkill;
    }

    void DrawSkills()
    {

        //if (selected_skill_index >= 0)
        //{
        //    if (styleSelectedSkill == null)
        //        styleSelectedSkill = new GUIStyle(GUI.skin.box);
        //    GUI.Box(GetSelectedSkilRect(), "", styleSelectedSkill);
        //}

        GUILayout.BeginVertical();



        GUILayout.BeginHorizontal();
        if (GUILayout.Button("+"))
        {
            skills.Add(new config_skill());
        }

        if (GUILayout.Button("-"))
        {
            if (selected_skill_index >= 0 && selected_skill_index < skills.Count)

                skills.RemoveAt(selected_skill_index);
        }

        GUILayout.EndHorizontal();


        string[] skill_names = new string[skills.Count];
        for (int i = 0; i < skill_names.Length; i++)
        {
            skill_names[i] = skills[i].id + " " + skills[i].name;
        }


        int index = GUILayout.SelectionGrid(selected_skill_index, skill_names, 1);
        if(index!=selected_skill_index)
        {
            selected_skill_index = index;

            skill = selected_skill;
                //使用当前类初始化
            _serializedObject = new SerializedObject(this);
            //获取当前类中可序列话的属性
            _assetLstProperty = _serializedObject.FindProperty("skill");
        }



        //for (int i = 0; i < skills.Count; i++)
        //{
        //    GUILayout.BeginHorizontal();

        //    GUILayout.Box(skills[i].id + " " + skills[i].name,GUILayout.ExpandWidth(true));
        //    if (GUILayout.Button("-"))
        //    {
        //        skills.RemoveAt(i);
        //    }
        //    //if (GUILayout.Button("v"))
        //    //{
        //    //    current_skill_frame = skill.frames[i];
        //    //}
        //    //skill.frames[i].action = (SkillFrameAction)EditorGUILayout.EnumPopup(skill.frames[i].action);


        //    GUILayout.EndHorizontal();
        //}

        
        float box_height = GUILayoutUtility.GetLastRect().height;






        GUILayout.EndVertical();

        Rect skillRect = GUILayoutUtility.GetLastRect();

        if (Event.current != null)
        {
            switch (Event.current.rawType)
            {
                case EventType.MouseDown:
                    if (skillRect.Contains(Event.current.mousePosition))
                    {
                        selected_skill_index =(int) (Event.current.mousePosition.y / box_height);
                    }
                    
                    break;

            }
        }

        ////更新
        //_serializedObject.Update();

        ////开始检查是否有修改
        //EditorGUI.BeginChangeCheck();

        ////显示属性
        ////第二个参数必须为true，否则无法显示子节点即List内容
        //EditorGUILayout.PropertyField(_assetLstProperty, true);

        ////结束检查是否有修改
        //if (EditorGUI.EndChangeCheck())
        //{
        //    //提交修改
        //    _serializedObject.ApplyModifiedProperties();
        //}
    }
#endif

        void DrawNodeCurve(Rect start, Rect end)
        {
            Vector3 startPos = new Vector3(start.x + start.width, start.y + start.height / 2, 0);
            Vector3 endPos = new Vector3(end.x, end.y + end.height / 2, 0);
            Vector3 startTan = startPos + Vector3.right * 50;
            Vector3 endTan = endPos + Vector3.left * 50;
            Color shadowCol = new Color(0, 0, 0, 0.06f);
            for (int i = 0; i < 3; i++) // Draw a shadow
                Handles.DrawBezier(startPos, endPos, startTan, endTan, shadowCol, null, (i + 1) * 5);
            Handles.DrawBezier(startPos, endPos, startTan, endTan, Color.black, null, 1);
        }

        void DrawFrames()
        {

            pos2 = GUILayout.BeginScrollView(pos2, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));


            GUILayout.BeginHorizontal();

            GUILayout.BeginVertical();

            GUILayout.Space(time_scale_height + grid_height + 10);

            GUILayout.EndVertical();
            GUILayout.Space(title_width + grid_width + 10);

            GUILayout.EndHorizontal();

            DrawF();


            GUILayout.EndScrollView();

        }

        int unit_width = 10;
        int unit_height = 20;
        int title_width = 110; //左边标题宽度
        int time_scale_height = 20; //刻度文字高度
        int grid_width
        {
            get { return _skill.frame_count * unit_width; }
        }
        int grid_height
        {
            get
            {
                return _skill.frames.Length * unit_height;
            }
        }

        void DrawF()
        {
            config_skill _skill = myTarget.skill;

            int gird_width = _skill.frame_count * unit_width;
            int gird_height = _skill.frames.Length * unit_height;


            //优化处理
            for (int i = 0; i < _skill.frames.Length; i++)
            {
                if (_skill.frames[i].frame_length <= 0)
                    _skill.frames[i].frame_length = 1;
                int min_frame_count = _skill.frames[i].frame_index + _skill.frames[i].frame_length;
                if (_skill.frame_count < min_frame_count)
                {
                    _skill.frame_count = min_frame_count;
                }
            }

            //背景
            {
                float offset_x = 0;
                float offset_y = 0;
                Handles.color = Color.white;
                Handles.DrawSolidRectangleWithOutline(new Rect(new Vector2(offset_x, offset_y), new Vector2(5000, 5000)), Color.white, Color.white);
            }

            //刻度
            {
                float offset_x = title_width;
                float offset_y = 0;

                Handles.color = Color.black;

                for (int i = 0; i <= _skill.frame_count; i++)
                {
                    int frame_count = i + 1;
                    if (frame_count != 1 && frame_count % 5 == 0 && i != _skill.frame_count)
                    {
                        Handles.Label(new Vector3(i * unit_width + offset_x, offset_y), frame_count.ToString());
                        //g.DrawString((frame_count).ToString(), font, Brushes.Black, new PointF(i * unit_width, 0));
                    }
                }
            }

            //表头
            {
                float offset_x = 0;
                float offset_y = time_scale_height;

                Handles.color = Color.black;

                for (int i = 0; i < _skill.frames.Length; i++)
                {
                    Handles.Label(new Vector3(0 + offset_x, unit_height * i + offset_y), _skill.frames[i].action.ToString());
                }
            }

            //格子，关键帧
            {

                float offset_x = title_width;
                float offset_y = time_scale_height;


                //竖线
                for (int i = 0; i <= _skill.frame_count; i++)
                {
                    Handles.color = Color.gray;
                    //g.DrawLine(pen, new Point(i * unit_width, 0), new Point(i * 10, gird_height));
                    Handles.DrawLine(new Vector3(i * unit_width + offset_x, offset_y), new Vector3(i * 10 + offset_x, gird_height + offset_y));
                    //关键帧数
                    int frame_count = i + 1;
                    if (frame_count != 1 && frame_count % 5 == 0 && i != _skill.frame_count)
                    {
                        //g.FillRectangle(brush_sp_key, i * unit_width, 0, unit_width, gird_height);
                        //Handles.RectangleCap(0, , Quaternion.identity, unit_width / 2);
                        Handles.color = new Color(Color.gray.r, Color.gray.g, Color.gray.b, 0.3f);
                        Handles.DrawSolidRectangleWithOutline(new Rect(new Vector2(i * unit_width + offset_x, offset_y), new Vector2(unit_width, gird_height)), Color.gray, Color.black);
                    }
                }
                //横线
                Handles.color = Color.gray;
                for (int i = 0; i <= _skill.frames.Length; i++)
                {
                    Handles.DrawLine(new Vector3(0 + offset_x, i * unit_height + offset_y), new Vector3(gird_width + offset_x, i * unit_height + offset_y));
                    //g.DrawLine(pen, new Point(0, i * unit_height), new Point(gird_width, i * unit_height));
                }

                //关键帧
                for (int i = 0; i < _skill.frames.Length; i++)
                {
                    int frame_index = _skill.frames[i].frame_index;
                    int frame_number = _skill.frames[i].frame_length;

                    Rect rect = new Rect(frame_index * unit_width + 1 + offset_x, i * unit_height + 1 + offset_y, frame_number * unit_width - 1, unit_height - 1);
                    Handles.DrawSolidRectangleWithOutline(rect, new Color(1f, 0, 0, 1), Color.black);
                }

                //选择效果
                if (myTarget.selected_frame_index >= 0)
                {
                    int width = gird_width + title_width;
                    Handles.color = new Color(0, 1, 0, 0.3f);
                    //Graphics g = e.Graphics;
                    //Brush selected_brush_frame = new SolidBrush(Color.FromArgb(50, Color.Green));
                    //g.FillRectangle(selected_brush_frame, 0, selected_frame_index * unit_height + time_scale_height, width, unit_height);
                    Rect rect = new Rect(0, myTarget.selected_frame_index * unit_height + offset_y, width, unit_height);
                    Handles.DrawSolidRectangleWithOutline(rect, Handles.color, Handles.color);
                }
            }
        }

        void DrawPropertys()
        {
#if DRAW_SKILL_LIST
        if (selected_skill != null && _serializedObject!=null)
        {
            //更新
            _serializedObject.Update();

            //开始检查是否有修改
            EditorGUI.BeginChangeCheck();

            //显示属性
            //第二个参数必须为true，否则无法显示子节点即List内容
            EditorGUILayout.PropertyField(_assetLstProperty, true);

            //结束检查是否有修改
            if (EditorGUI.EndChangeCheck())
            {//提交修改
                _serializedObject.ApplyModifiedProperties();
            }
        }
#else

#endif
            //if (od != null)
            //    od.OnGUI();

            //GUILayout.Space(20);
            //EditorGUI.indentLevel++;
            //GUILayout.BeginVertical(  );
            //if (cacheEditor!=null)
            //    cacheEditor.OnInspectorGUI();
            //GUILayout.EndVertical();
            //EditorGUI.indentLevel--;
        }


        //void Update()
        //{

        //    if(Input.GetMouseButtonDown(0))
        //    {
        //        OnLeftMouseDown();
        //    }
        //    else if(Input.GetMouseButton(0))
        //    {
        //        if(Input.mousePosition!=_lastMouseLocation)
        //        {
        //            OnLeftMouseMove();
        //        }
        //    }
        //    else if(Input.GetMouseButtonUp(0))
        //    {
        //        OnLeftMouseUp();
        //    }
        //}

        void OnLeftMouseDown()
        {

            Vector2 Location = Event.current.mousePosition + pos2;


            var titleRect = new Rect(0, time_scale_height, title_width, grid_height);

            if (titleRect.Contains(Location))
            {
                Dictionary<string, List<string>> items = new Dictionary<string, List<string>>();
                items["通用"] = new List<string>();


                var menu = new GenericMenu();


                string[] typeSkillFrameActionNames = System.Enum.GetNames(typeof(SkillFrameAction));
                System.Type typeSkillFrameAction = typeof(SkillFrameAction);
                foreach (var s in typeSkillFrameActionNames)
                {
                    System.Reflection.FieldInfo fi = typeSkillFrameAction.GetField(s);
                    EditorNameAttribute menuNameAttribute = GetCustomAttribute<EditorNameAttribute>(fi);
                    //List<string> menuItems = new List<string>();
                    string item = s;
                    if (menuNameAttribute == null)
                    {
                        item = "通用/" + s;
                        //menuItems.Add("通用");
                        //menuItems.Add(s);
                    }

                    menu.AddItem(new GUIContent(item), false, OnActionChange, s);
                }


                menu.ShowAsContext();
            }

            var contextRect = new Rect(0, time_scale_height, title_width + grid_width, grid_height);

            if (contextRect.Contains(Location))
            {

                //选择行
                if (_skill != null && _skill.frames != null)
                {
                    int selected_line_index = (int)((Location.y - time_scale_height) / unit_height);
                    if (selected_line_index >= 0 && selected_line_index < _skill.frames.Length)
                    {
                        selected_frame_index = selected_line_index;

                        //if (onSelectFrame != null)
                        //    onSelectFrame(selected_line_index);

                        //Refresh();
                        //myTarget.current_skill_frame = _skill.frames[selected_frame_index];

                        Repaint();
                    }



                }


                //编辑
                if (selected_frame != null)
                {
                    int x_frame_index = (int)((Location.x - title_width) / unit_width);


                    if (x_frame_index == selected_frame.frame_index)
                    {
                        _mode = EditMode.Move;
                        _lastMouseLocation = Location;
                    }
                    else
                    {
                        //记录起始帧
                        selected_start_frame_index = x_frame_index;
                        _mode = EditMode.SelectFrame;
                        _lastMouseLocation = Location;
                    }


                }
            }





        }
        void OnLeftMouseMove()
        {
            Vector2 Location = Event.current.mousePosition;
            if (_mode == EditMode.Move)
            {
                if (Event.current.control)
                {
                    float x_frame_pos = ((float)(Location.x - title_width)) / unit_width;
                    selected_frame.frame_length = (int)x_frame_pos - selected_frame.frame_index;// Math.Max(frameIndexToTime(x_frame_pos) - selected_frame.time, 0);
                    selected_frame.frame_length = Math.Max(1, selected_frame.frame_length);

                }
                else
                {
                    float x_frame_pos = ((float)(Location.x - title_width)) / unit_width;
                    selected_frame.frame_index = Math.Max((int)x_frame_pos, 0);// Math.Max(frameIndexToTime(x_frame_pos), 0);

                }


                if (onActionChange != null)
                    onActionChange();

                MarkSceneDirty();
                Repaint();
            }
            //else if (_mode == EditMode.SelectFrame)
            //{
            //    if (e.Button == System.Windows.Forms.MouseButtons.Left)
            //    {
            //        float x_frame_pos = ((float)(e.Location.X - title_width)) / unit_width;
            //        selected_end_frame_index = (int)x_frame_pos;
            //        Refresh();
            //    }

            //}
        }
        void OnLeftMouseUp()
        {
            _mode = EditMode.None;
        }


        void OnPopupMenuAdd()
        {
            config_skill_frame new_frame = new config_skill_frame();
            List<config_skill_frame> newList = new List<config_skill_frame>(_skill.frames);
            newList.Add(new_frame);
            _skill.frames = newList.ToArray();
            MarkSceneDirty();
            Repaint();

        }

        void OnPopupMenuDup()
        {
            if (selected_frame != null)
            {
                //MemoryStream ms = new MemoryStream();
                //ProtoBuf.Serializer.Serialize(ms, frame1.selected_frame);
                //ms.Position = 0;
                //config_skill_frame new_frame = ProtoBuf.Serializer.Deserialize<config_skill_frame>(ms);
                config_skill_frame new_frame = ProtoBuf.Serializer.DeepClone(selected_frame);
                List<config_skill_frame> newList = new List<config_skill_frame>(_skill.frames);
                newList.Add(new_frame);
                _skill.frames = newList.ToArray();
                MarkSceneDirty();
                Repaint();
            }


        }
        void OnPopupMenuDel()
        {
            if (selected_frame != null)
            {
                List<config_skill_frame> newList = new List<config_skill_frame>(_skill.frames);
                newList.Remove(selected_frame);
                _skill.frames = newList.ToArray();
                MarkSceneDirty();
                Repaint();
            }
        }
        void OnPopupMenuCopy()
        {
            if (selected_frame != null)
            {
                temp_frame = selected_frame;
            }
        }
        void OnPopupMenuPrase()
        {
            if (temp_frame != null && _skill != null)
            {
                config_skill_frame new_frame = ProtoBuf.Serializer.DeepClone(temp_frame);
                List<config_skill_frame> newList = new List<config_skill_frame>(_skill.frames);
                newList.Add(new_frame);
                _skill.frames = newList.ToArray();
                MarkSceneDirty();
                Repaint();
            }
        }


        public class CustomTypeDrawer
        {
            XProps props;
            string _name = "";
            List<CustomPropertyDrawer> drawers;
            public object obj;
            public CustomTypeDrawer(object obj, bool defaultOpenDepth1 = true)
            {
                this.obj = obj;
                props = new XProps(obj);
                PropertyDescriptorCollection properties = props.GetProperties();
                drawers = new List<CustomPropertyDrawer>();
                foreach (var f in properties)
                {
                    CustomPropertyDrawer p = new CustomPropertyDrawer((PropertyDescriptor)f);
                    drawers.Add(p);
                    if (defaultOpenDepth1)
                        p.hide = false;
                }
            }

            bool _hide = true;
            public bool hide
            { get { return _hide; } set { _hide = value; } }
            public void OnGUI()
            {
                //_hide = !EditorGUILayout.Foldout(!_hide, _name);
                //if (!_hide)
                {
                    //EditorGUI.indentLevel++;
                    EditorGUILayout.BeginVertical();
                    foreach (var f in drawers)
                    {
                        f.OnGUI();
                    }
                    EditorGUILayout.EndVertical();
                    //EditorGUI.indentLevel--;
                }

            }

            public void RefreshObject(object o)
            {
                foreach (var f in drawers)
                {
                    f.RefreshObject(o);
                }
            }
        }

        public class CustomPropertyDrawer
        {
            public static System.Action<object> onSelectProperty;

            PropertyDescriptor prop;
            List<CustomPropertyDrawer> drawers;
            public CustomPropertyDrawer(PropertyDescriptor p)
            {
                prop = p;
                ConstructDrawers();
            }

            public void RefreshObject(object o)
            {
                object v = prop.GetValue(null);

                if (v == o)
                {
                    ConstructDrawers();
                    return;
                }

                if (drawers == null)
                    return;

                foreach (var d in drawers)
                    d.RefreshObject(o);
            }

            void ConstructDrawers()
            {
                object v = prop.GetValue(null);
                if (v == null)
                {
                    drawers = null;
                    return;
                }

                PropertyDescriptorCollection properties = prop.Converter.GetProperties(null, v, null);
                if (properties != null && properties.Count > 0)
                {
                    if (drawers == null)
                        drawers = new List<CustomPropertyDrawer>();
                    else if (drawers.Count > properties.Count)
                    {
                        int count = drawers.Count - properties.Count;
                        drawers.RemoveRange(drawers.Count - count, count);
                    }

                    for (int i = 0; i < properties.Count; i++)
                    {
                        if (i < drawers.Count)
                        {
                            if (drawers[i].prop == properties[i])
                            {

                            }
                            else
                            {
                                drawers[i].prop = properties[i];
                                drawers[i].ConstructDrawers();
                            }
                        }
                        else
                        {
                            drawers.Add(new CustomPropertyDrawer(properties[i]));
                        }
                    }
                }
                else
                {
                    drawers = null;
                }
            }

            bool _hide = true;
            public bool hide
            { get { return _hide; } set { _hide = value; } }

            public void OnGUI()
            {
                Type type = prop.PropertyType;
                object v = prop.GetValue(null);
                TypeConverter tc = prop.Converter;
                GUIContent name = new GUIContent(prop.DisplayName, prop.Description);
                //EditorGUILayout.BeginHorizontal();

                if (type == typeof(bool))
                {
                    v = EditorGUILayout.Toggle(name, (bool)v, GUILayout.MinWidth(100));
                    prop.SetValue(null, v);
                }
                else if (type == typeof(int))
                {
                    v = EditorGUILayout.IntField(name, (int)v);
                    prop.SetValue(null, v);
                }
                else if (type == typeof(float))
                {
                    v = EditorGUILayout.FloatField(name, (float)v);
                    prop.SetValue(null, v);
                }
                else if (type == typeof(Color))
                {
                    Color tempV = (Color)v;
                    v = (Color)EditorGUILayout.ColorField(name, tempV);
                    prop.SetValue(null, v);
                }
                else if (type.IsArray)
                {
                    EditorGUILayout.BeginVertical();

                    bool last_hide = _hide;

                    _hide = !EditorGUILayout.Foldout(!_hide, name);


                    if (!_hide)
                    {
                        EditorGUI.indentLevel++;

                        System.Array array = (System.Array)v;
                        if (array == null)
                        {
                            array = System.Array.CreateInstance(type.GetElementType(), 0);
                            prop.SetValue(null, array);
                            ConstructDrawers();
                        }

                        int size = EditorGUILayout.IntField("Size", array.Length);
                        if (size != array.Length && size >= 0)
                        {
                            System.Array newArray = System.Array.CreateInstance(type.GetElementType(), size);
                            int copy_size = Mathf.Min(size, array.Length);

                            if (copy_size > 0)
                            {
                                Array.Copy(array, 0, newArray, 0, copy_size);
                            }
                            for (int i = copy_size; i < newArray.Length; i++)
                            {
                                if (type.GetElementType().IsArray)
                                {
                                    newArray.SetValue(System.Array.CreateInstance(type.GetElementType().GetElementType(), 0), i);
                                }
                                else
                                {
                                    newArray.SetValue(System.Activator.CreateInstance(type.GetElementType()), i);
                                }
                            }

                            array = newArray;
                            prop.SetValue(null, array);
                            ConstructDrawers();
                        }
                        if (drawers != null && array.Length != drawers.Count)
                        {
                            ConstructDrawers();
                        }


                        v = array;

                        if (v != null && drawers != null)
                        {

                            EditorGUILayout.BeginVertical();
                            foreach (var d in drawers)
                            {
                                d.OnGUI();
                            }
                            EditorGUILayout.EndVertical();

                        }
                        EditorGUI.indentLevel--;
                    }

                    if (last_hide != _hide && v != null)
                    {
                        if (onSelectProperty != null)
                            onSelectProperty(v);
                    }


                    EditorGUILayout.EndVertical();

                }
                else if (type.IsEnum)
                {
                    v = EditorGUILayout.EnumPopup(name, (System.Enum)v, GUILayout.MinWidth(100));
                    prop.SetValue(null, v);
                }
                else if (type == typeof(Vector2))
                {
                    Vector2 tempV = (Vector2)v;
                    v = EditorGUILayout.Vector2Field(name, tempV);
                    prop.SetValue(null, v);
                }
                else if (type == typeof(Vector3))
                {
                    Vector3 tempV = (Vector3)v;
                    v = EditorGUILayout.Vector3Field(name, tempV);
                    prop.SetValue(null, v);
                }
                else if (type.IsPrimitive || type == typeof(string))
                {
                    //EditorGUILayout.LabelField(name, GUILayout.MinWidth(100));
                    string str_v = EditorGUILayout.TextField(name, tc.ConvertToString(v), GUILayout.MinWidth(100));
                    v = tc.ConvertFromString(str_v);
                    prop.SetValue(null, v);
                }
                else if ((type.IsClass || type.IsValueType))
                {
                    bool last_hide = _hide;
                    _hide = !EditorGUILayout.Foldout(!_hide, name);
                    if (last_hide != _hide && v != null)
                    {
                        if (onSelectProperty != null)
                            onSelectProperty(v);
                        SceneView.RepaintAll();
                    }

                    if (v != null && !_hide && drawers != null)
                    {

                        EditorGUI.indentLevel++;
                        EditorGUILayout.BeginVertical();
                        foreach (var d in drawers)
                        {
                            d.OnGUI();
                        }
                        EditorGUILayout.EndVertical();
                        EditorGUI.indentLevel--;
                    }
                }


                //EditorGUILayout.EndHorizontal();




            }
        }

    }
}